#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "communicationmanager.h"
#include "protocolhandler.h"
#include <QMainWindow>
#include <QSerialPort>
#include <QtCore>
#include <QtGui>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QList>
#include <QRegExp>
#include <QMessageBox>
#include <QFile>
#include <QFileDialog>
#include <QDateTime>
#include <QElapsedTimer>
#include <QTextEdit>
#include <QTextCodec>
#include <QSettings>
#include <QProgressDialog>
QT_BEGIN_NAMESPACE

namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    //将Widget设计成单例模式
    static Widget* getInstance() {
        static Widget instance;
        return &instance;
    }
    //获取ControlResponse数组的值
    static QByteArray& getControlResponse() {
        return controlResponse;
    }

    CommunicationManager *communicationManager;//通信类实例
    ProtocolHandler *protocol;//报文类实例

    QByteArray rest_data;//存储复位命令数据
    QByteArray com_data;//存储通讯命令数据
    QByteArray flash_data;//存储清除Flash命令数据
    QByteArray exist_data;//存储测试存在命令数据

    static QByteArray controlResponse;//控制类响应报文数组



    QByteArray responseForPacket;///存储第一个数据包的响应
    QByteArray responseForFlashData;//存储发送flash后的响应


    //停止checkTimer（定时器，用于接收复位响应）
    void stopCheckTimer();
    // 获取时间戳并和响应数组一起显示在指定控件上
    void displayDataInLog(const QByteArray &displayStr);

    //获取isFirstPacketSent的状态
    bool getIsFirstPacketSent();

public slots:
    //接收清空flash的响应，并发送第一个数据包
  //  void checkResponseAndSendFirstPacket();
    //发送剩余的数据包
    void sendRemainingPackets();
    //检查接收到的第一个数据包的响应
    void checkFirstPacketResponse();
    //检查写入数据接受的 清除flash 响应
    void checkFlashDataResponse();
    //检查写入数据接收的 最后一个数据包 的响应
    void checkLastPackResponse();




private slots:
    //控制类响应的超时函数
    void handleControlTimeout();
    //实现每10ms发送一次通信命令的槽函数
    void relationTimerout();
    //实现循环接收 复位 响应是否符合的超时函数
    void checkResponseTimerout();
    //实现循环接收 通信 响应是否符合的超时函数
    void checkComResponseTimerout();
    //实现循环接收 清除Flash 响应是否符合的超时函数
    void checkFlashResponseTimerout();
    //实现循环接收 测试存在 响应是否符合的超时函数
    void checkExistResponseTimerout();
    // 复合指令1 接收复位指令的超时函数
    void checkCompoundResponse();



    //连接串口按钮
    void on_pushButton_connect_clicked();
    //建立通信
    void openSerialPort();


    //点击复位按钮发送复位数据
    void on_pushButton_restoration_clicked();
    //复位命令CRC计算
    void rest_updateCRC();
    //点击 更新 复位命令
    void on_Button_refres_clicked();

    //点击通信按钮
    void on_pushButton_common_clicked();
    //点击通信 更新 命令按钮
    void on_Button_com_refres_clicked();
    //通讯命令CRC计算
    void com_updateCRC();

    //点击清除Flash按钮
    void on_Button_Falsh_clicked();
    //点击 更新 Flash命令显示
    void on_Button_flash_refres_clicked();
    //清除Flash命令CRC计算
    void flash_updateCRC();

    //点击测试存在按钮
    void on_Button_exist_clicked();
    //点击 更新 测试存在命令显示
    void on_Button_exist_refres_clicked();
    //测试存在命令CRC计算
    void exist_updateCRC();

    //点击 复合指令1
    void on_Button_compound_clicked();


    //点击 写入数据 按钮
    void on_Button_write_clicked();


    //保存数据
    void saveSettings();
    //加载数据
    void loadSettings();


signals:

private:
    Ui::Widget *ui;

    QTimer *checkTimer;  // 定时器，用于接收控制类复位响应
    QTimer *relationTimer;//用来每间隔10ms发送一次通信命令
    QTimer *checkResponseTimer;//检查复位响应是否符合条件的定时器
    QTimer *checkComResponseTimer;//检查通信响应是否符合条件的定时器
    QTimer *checkFlashResponseTimer;//检查清除Flash响应是否符合条件的定时器
    QTimer *checkExistResponseTimer;//检查清除Flash响应是否符合条件的定时器
    QTimer *compoundTimer;//用来强制退出接收复位指令循环的定时器
    QTimer *checkComTimer;//用来检查 复合指令1 接收到的复为响应
    QElapsedTimer compoundElapsedTimer; // 用于记录复位响应检查的时间
    QTimer *loadFlashTimer;//用来接收载入数据第一次接收flash响应的定时器
    QTimer *loadFristDataTimer;//用来接收载入数据第一次接收数据包响应的定时器
    QTimer *loadLastDataTimer;//用来接收在输入是最后一滴接收数据包响应的定时器
    int compoundFlag;//计数器，用来确保接收两次复位响应后，发送通讯命令

    QMessageBox* promptMessage;//用来关闭数据载入的提示框

    QList<QByteArray> packets;//用来存储载入数据的容器


    //关闭所有计时器
    void stopAndDeleteTimer(QTimer*& timer);


    void update_rest_ArrayData(); // 更新复位数组数据的方法
    void update_com_ArrayData(); // 更新通讯数组数据的方法
    void update_flash_ArrayData(); // 更新flash数组数据的方法
    void update_exist_ArrayData();//更新测试存在数组数据的方法

};
#endif // WIDGET_H
